package com.bifang.module.file.core.util;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import com.bifang.engine.assistant.core.enums.BoolEnum;
import com.bifang.engine.assistant.core.exception.AppException;
import com.bifang.module.file.common.vo.FileClassVO;
import com.bifang.module.file.common.vo.FileInfoVO;
import com.bifang.module.file.common.util.Encode;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;

/** 本地文件处理类 */
@Component
public class FileLocalUtil {
    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    // 默认路径
    @Value("${system.config.file.default.base.path}")
    private String defaultPath;

    @Autowired private FileCommonUtil fileCommonUtil;

    /** 本地上传 */
    public Boolean upload(MultipartFile file, FileClassVO fileClassVO, FileInfoVO fileInfoVO) {

        if (StringUtils.isBlank(fileClassVO.getFileBasePath())) {
            fileClassVO.setFileBasePath(defaultPath);
        }
        fileCommonUtil.initFile(file, fileClassVO, fileInfoVO);
        // 校验文件是否可以上传
        fileCommonUtil.checkFile(fileInfoVO.getFileSuffix(), fileInfoVO.getFileSize(), fileClassVO);
        String path =
                fileCommonUtil.getPath(fileClassVO.getFileBasePath(), fileInfoVO.getFilePath());
        try {
            if (FileUtil.exist(path)) {
                if (fileInfoVO.getForceFlag()) {
                    FileUtil.del(path);
                } else {
                    return true;
                }
            }
            FileUtil.writeFromStream(file.getInputStream(), path);
            this.encryption(path, fileInfoVO);

        } catch (IOException e) {
            logger.error("文件拷贝异常", e);
            throw new AppException("文件拷贝异常" + e.getMessage());
        }

        return true;
    }

    /** 本地上传 */
    public Boolean upload(File file, FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        if (StringUtils.isBlank(fileClassVO.getFileBasePath())) {
            fileClassVO.setFileBasePath(defaultPath);
        }
        // 本地作为文件服务器
        fileCommonUtil.initFile(file, fileClassVO, fileInfoVO);
        // 校验文件是否可以上传
        fileCommonUtil.checkFile(fileInfoVO.getFileSuffix(), fileInfoVO.getFileSize(), fileClassVO);
        String path =
                fileCommonUtil.getPath(fileClassVO.getFileBasePath(), fileInfoVO.getFilePath());
        // 判断文件是否存在
        if (FileUtil.exist(path)) {
            if (fileInfoVO.getForceFlag()) {
                FileUtil.del(path);
            } else {
                return true;
            }
        }

        try {
            FileUtil.copy(file.getAbsolutePath(), path, true);
            this.encryption(path, fileInfoVO);
        } catch (Exception e) {
            throw new AppException("文件拷贝异常" + e.getMessage());
        }

        return true;
    }

    /** 本地上传 */
    public Boolean upload(byte[] file, FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        InputStream sbs = new ByteArrayInputStream(file);
        return this.upload(sbs, fileClassVO, fileInfoVO);
    }

    /** 本地上传 */
    public Boolean upload(InputStream in, FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        try {
            if (StringUtils.isBlank(fileClassVO.getFileBasePath())) {
                fileClassVO.setFileBasePath(defaultPath);
            }
            // 本地作为文件服务器
            fileCommonUtil.initFile(in, fileClassVO, fileInfoVO);
            // 校验文件是否可以上传
            fileCommonUtil.checkFile(
                    fileInfoVO.getFileSuffix(), fileInfoVO.getFileSize(), fileClassVO);
            String path =
                    fileCommonUtil.getPath(fileClassVO.getFileBasePath(), fileInfoVO.getFilePath());
            // 判断文件是否存在
            if (FileUtil.exist(path)) {
                if (fileInfoVO.getForceFlag()) {
                    FileUtil.del(path);
                } else {
                    return true;
                }
            }
            FileUtil.writeFromStream(in, path);
            this.encryption(path, fileInfoVO);

        } catch (Exception e) {
            throw new AppException("文件拷贝异常" + e.getMessage());
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.error("关闭流异常，", e);
                }
            }
        }
        return true;
    }

    private void encryption(String path, FileInfoVO fileInfoVO) {
        if (StringUtils.isNotBlank(fileInfoVO.getEncryptionFlag())) {
            if (BoolEnum.TRUE.getType().endsWith(fileInfoVO.getEncryptionFlag())) {
                fileInfoVO.setFilePassowrd(RandomUtil.randomString(5));
                new Encode(true, path, fileInfoVO.getFilePassowrd()).run();
            }
        } else {
            fileInfoVO.setEncryptionFlag(BoolEnum.FALSE.getType());
        }
    }

    /** 本地下载 */
    public File download(FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        if (StringUtils.isBlank(fileInfoVO.getFilePath())) {
            return null;
        }
        if (StringUtils.isBlank(fileClassVO.getFileBasePath())) {
            fileClassVO.setFileBasePath(defaultPath);
        }
        String path =
                fileCommonUtil.getPath(fileClassVO.getFileBasePath(), fileInfoVO.getFilePath());
        if (!FileUtil.exist(path)) {
            throw new AppException("文件不存在");
        }
        // 解密文件
        String fileName = fileInfoVO.getFileMd5() + "." + fileInfoVO.getFileSuffix();
        File file = null;
        if (BoolEnum.TRUE.getType().equals(fileInfoVO.getEncryptionFlag())) {
            if (fileInfoVO.getForceFlag()) {
                fileCommonUtil.delTempFileDownloadByName(fileName);
            }
            file = fileCommonUtil.createTempFileDownload(path, fileName);
            new Encode(false, file, fileInfoVO.getFilePassowrd()).run();
            return file;
        }
        return FileUtil.file(path);
    }

    /** 本地删除 */
    public void delete(FileInfoVO fileInfoVO) {
        String path =
                fileCommonUtil.getPath(fileInfoVO.getFileBasePath(), fileInfoVO.getFilePath());
        if (FileUtil.exist(path)) {
            Boolean flag = FileUtil.del(path);
            if (!flag) {
                throw new AppException("删除文件失败");
            }
        }
    }

    public String getBase64(FileClassVO fileClassVO, FileInfoVO fileInfoVO) {
        File file = this.download(fileClassVO, fileInfoVO);
        if (file == null) {
            throw new AppException("文件不存在");
        }
        Long length = file.length();
        fileCommonUtil.checkBase64(length);
        return Base64.encode(file);
    }
}
